﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Ehai.Web.Framework.Rules
{
    class DirRuleHandle : IMsgRuleHandle
    {

        #region IMsgRuleHandle 成员


#if DEBUG

        private int _execStatus = 0;
        public int ExecStatus
        {
            get { return _execStatus; }
        }

#endif

        public const string Name = "dir";

        public string GetHelpInfo()
        {
            return "文件、文件夹的信息";
        }

        public string GetHelpDetail()
        {
            return "获得目录下所有文件、文件夹的信息,参数范例：{ dir, *, [Size,Name,Type], E:test, mytest }<br />";
        }

        public string[] GetParametersInfo()
        {
            string[] t = new string[5];
            t[0] = "[0](必选)处理类型,即\"dir\"";
            t[1] = "[1](可空)搜索文件";
            t[2] = "[2](可空)文件属性";
            t[3] = "[3]文件根目录";
            t[4] = "[4]相对路径";
            return t;
        }


        #region 获得文件和文件夹属性
        /// <summary>
        /// 返回目录大小 
        /// </summary>
        /// <param name="d">目录信息</param>
        /// <returns>目录大小，类型为long</returns>
        private static long DirSize(DirectoryInfo d)
        {
            long Size = 0;
            // 所有文件大小.
            FileInfo[] fis = d.GetFiles();
            foreach (FileInfo fi in fis)
            {
                Size += fi.Length;
            }
            // 遍历出当前目录的所有文件夹.
            DirectoryInfo[] dis = d.GetDirectories();
            foreach (DirectoryInfo di in dis)
            {
                Size += DirSize(di);   //这就用到递归了，调用父方法,注意，这里并不是直接返回值，而是调用父返回来的
            }
            return (Size);
        }
        /// <summary>
        /// 返回文件属性
        /// </summary>
        /// <param name="d">文件信息</param>
        /// <param name="type">属性类别</param>
        /// <returns>属性值</returns>
        public static string fileAttribute(FileInfo d, string type)
        {
            string attr = "";
            switch (type)
            {
                case "Name":
                    attr = d.Name;
                    break;
                case "Size":
                    attr = transformUnit(d.Length);
                    break;
                case "Time":
                    attr = d.LastWriteTime.ToString();
                    break;
                case "Attribute":
                    attr = d.Attributes.ToString();
                    break;
                case "Readonly":
                    attr = d.IsReadOnly ? "RA" : "A";
                    break;
                case "Type":
                    attr = "File";
                    break;
                default:
                    break;
            }
            return attr;
        }
        /// <summary>
        /// 返回文件夹属性
        /// </summary>
        /// <param name="d">文件夹信息</param>
        /// <param name="type">属性类别</param>
        /// <returns>属性值</returns>
        public static string directoryAttribute(DirectoryInfo d, string type)
        {
            string attr = "";
            switch (type)
            {
                case "Name":
                    attr = d.Name;
                    break;
                case "Size":
                    attr = transformUnit(DirSize(d));
                    break;
                case "Time":
                    attr = d.LastWriteTime.ToString();
                    break;
                case "Attribute":
                    attr = d.Attributes.ToString();
                    break;
                case "Readonly":
                    attr = "";
                    break;
                case "Type":
                    attr = "Dir";
                    break;
                default:
                    break;
            }
            return attr;
        }
        private static string transformUnit(long size)
        {
            if (size < 1024)
                return "1KB";
            else if (size < 1048576)
                return (size / 1024).ToString() + "KB";
            else
                return (size / 1048576).ToString() + "MB";

        }
        #endregion

        #region 获得目录下所有文件、文件夹的信息

        /// <summary>
        /// 获得目录下所有文件、文件夹的信息
        /// </summary>
        /// <param name="p">
        /// 传入数组，所有参数必选<br />
        /// 0:(必选)处理类型 必须是“dir”<br />
        /// 1:(可空)搜索文件，（可使用"*"、"?"进行字符匹配）a：表示文件名中有“a”的文件.如传入null或Empty，默认*<br />
        /// 2:(可空)文件属性，用逗号隔开,Name Size Time Attribute Readonly Type(返回File或Dir)，也可以用*代表所有。传入null或Empty默认*<br />
        /// 3:(必选)文件根目录<br />
        /// 4:(必选)相对路径<br />
        /// </param>
        /// <param name="ci">环境变量</param>
        /// <example>示例</example><code>
        /// string[] a = { "dir", "*", "Size,Name,Type", @"E:\test", @"mytest" };
        /// string[][] list=Execute(a); //查询E:\test\mytest下的所有项的Size，Name和Type
        /// </code>
        /// <exception cref="Ehai.Web.Framework.WebException">
        /// Ehai.Web.Framework.WebException:文件列表获取错误！
        /// </exception>
        /// <returns>第一维索引是从0开始的文件序号，第二维索引是从0开始的属性序号，按照传入顺序<br />
        /// 传入路径不存在或缺少参数将返回null
        /// </returns>

        public string[][] Execute(string[] p, ContextInfo ci)
        {
            if (p.Length < 5)
            {

#if DEBUG
                _execStatus = -2;
#endif

                return null;
            }

            if (string.IsNullOrEmpty(p[1]))
            {
                p[1] = "*";

#if DEBUG
                _execStatus = 1;
#endif

            }
            if (string.IsNullOrEmpty(p[2]) || p[2] == "*")
            {
                p[2] = "Name,Size,Time,Attribute,Readonly,Type";

#if DEBUG
                _execStatus = 2;
#endif

            }
            if (p[3] == null)
            {
                p[3] = string.Empty;

#if DEBUG
                _execStatus = 3;
#endif

            }
            if (p[4] == null)
            {
                p[4] = string.Empty;

#if DEBUG
                _execStatus = 4;
#endif

            }
            try
            {
                //路径的组合
                string path;

                p[4] = p[4].Trim().TrimStart(Path.DirectorySeparatorChar.ToString().ToCharArray());
                path = Path.Combine(p[3], p[4]);

                //路径的判断
                if (!Directory.Exists(path)) return null;

                string[] attr = p[2].Split(',');

                string[][] flist = null;    //返回值


                string[] fileList = Directory.GetFileSystemEntries(path, p[1]);

                flist = new string[fileList.Length][];

                for (int i = 0; i < fileList.Length; i++)
                    if (Directory.Exists(fileList[i]))
                    {
                        flist[i] = new string[attr.Length];
                        DirectoryInfo myFile = new DirectoryInfo(fileList[i]);
                        for (int j = 0; j < attr.Length; j++)
                            flist[i][j] = directoryAttribute(myFile, attr[j]);

                    }
                    else if (File.Exists(fileList[i]))
                    {
                        flist[i] = new string[attr.Length];
                        FileInfo myFile = new FileInfo(fileList[i]);
                        for (int j = 0; j < attr.Length; j++)
                            flist[i][j] = fileAttribute(myFile, attr[j]);
                    }

#if DEBUG
                _execStatus = 0;
#endif

                return flist;
            }
            catch (Exception ex)
            {

#if DEBUG
                _execStatus = -1;
#endif

                throw new Ehai.Web.Framework.WebException("Ehai.WebFramework.Rules.Dir", "文件列表获取错误！", ex);
            }
        }

        #endregion
    }
        #endregion
}